 ///
 /// @file    arrow.cc
 /// @author  lemon(haohb13@gmail.com)
 /// @date    2023-04-27 16:26:33
 ///
 
#include <iostream>
using std::cout;
using std::endl;


class Data
{
public:
	Data() {	cout << "Data()" << endl;	}
	~Data() {	cout << "~Data()" << endl;	}

	int getlength() const 
	{	return 10;	}
	
	int _data = 1;
};

class MiddleLayer
{
public:
	//在构造函数中托管堆空间的对象 Data
	MiddleLayer(Data * pdata)
	: _pdata(pdata)
	{	cout << "MiddleLayer(Data*)" <<  endl;	}

	//箭头运算符的重载
	Data * operator->()
	{	return _pdata;	}

	//解引用运算符
	Data & operator*()
	{	return *_pdata;	}

	//在析构函数中，回收托管的堆空间对象Data
	~MiddleLayer() {
		cout << "~MiddleLayer()" << endl;
		if(_pdata) {
			delete _pdata;
			_pdata = nullptr;
		}
	}

private:
	Data * _pdata;
};

class ThirdLayer
{
public:
	ThirdLayer(MiddleLayer * pml)
	: _pml(pml)
	{	cout << "ThirdLayer(MiddleLayer*)" << endl;	}

	//箭头运算符的返回值可以是一个指针或者是
	//重载了箭头运算符的对象 
	MiddleLayer & operator->()
	{	return *_pml;	}

	~ThirdLayer()
	{
		cout << "~ThirdLayer()" << endl;
		if(_pml) {
			delete _pml;
			_pml = nullptr;
		}
	}

private:
	MiddleLayer * _pml;
};
 
void test0() 
{
	//ml本身是一个对象，但其使用像一个指针了
	//这是一个智能指针的雏形, RAII的技术
	//
	//智能的含义：释放对象是自动进行的，不需要手动进行
	//
	//当MiddleLayer内部重载了箭头运算符和指针访问运算符时，
	//就是为了通过箭头和解引用运算符将对象转换为另外一个对象
	MiddleLayer ml(new Data());
	cout << ml->getlength() << endl;//简化操作
	cout << (ml.operator->())->getlength() << endl;//完整形式

	cout << (*ml).getlength() << endl;
	cout << (ml.operator*()).getlength() << endl;
	cout << endl;

	//这里可以了解可以，不要求掌握
	//缺点：代码可读性不强
	/* ThirdLayer tl(new MiddleLayer(new Data())); */
	/* cout << tl->getlength() << endl;//简化形式 */
	/* //完整形式 */
	/* cout << ((tl.operator->()).operator->())->getlength() << endl; */

} 
 
int main(void)
{
	test0();
	return 0;
}
